package cn.net.sinodata.system.msghandler.parse.scripthandler;

import cn.hutool.core.util.StrUtil;
import groovy.lang.GroovyShell;
import groovy.lang.Script;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Component;

import java.io.File;
import java.util.HashMap;
import java.util.Map;

/**
 * 脚本预加载及热加载处理 TODO 如何实现页面刷新
 */
@Slf4j
@Component
public class ScriptLoader {

    private static final Map<String, Script> scriptMap = new HashMap<>();

    @Autowired
    private ResourceLoader resourceLoader;

    /**
     * 脚本预加载
     * @param path 脚本资源路径
     * @throws Exception
     */
    public void preloader(String path) throws Exception {
        if (StrUtil.isEmpty(path)) {
            throw new Exception("脚本预加载失败：路径为空");
        }
        // 判断是classpath还是绝对路径
        File scriptDirFile;
        if (path.startsWith("classpath:") || path.startsWith("classpath*:")) {
            Resource resource = resourceLoader.getResource(path);
            if (!resource.exists()) {
                log.warn("脚本预加载失败：classpath下脚本资源不存在:" + path);
                throw new Exception("脚本预加载失败：classpath下脚本资源不存在:" + path);
            }
            scriptDirFile = resource.getFile();
        } else {
            scriptDirFile = new File(path);
        }

        // 判断路径是否存在
        if (!scriptDirFile.exists() && !scriptDirFile.isDirectory()) {
            log.warn("脚本预加载失败：脚本目录不存在或不是目录" );
            throw new Exception("脚本预加载失败：脚本目录不存在或不是目录");
        }
        load(scriptDirFile);
    }

    /**
     * 脚本预加载
     * @param scriptFiles 脚本资源路径或文件
     * @throws Exception
     */
    public void load(File scriptFiles) throws Exception {
        GroovyShell groovyShell = new GroovyShell();

        if (!scriptFiles.exists()) {
            log.warn("脚本加载失败：脚本目录或文件不存在" );
            throw new Exception("脚本加载失败：脚本目录或文件不存在");
        }

        File[] files;
        if (scriptFiles.isDirectory()) {
            files = scriptFiles.listFiles();
        } else {
            files = new File[]{scriptFiles};
        }

        for (File scriptFile : files) {
            String scriptName = scriptFile.getName();
            if (!scriptName.endsWith(".groovy")) {
                log.warn(scriptName + "不是groovy脚本");
                continue;
            }
            String[] splitNameArr = scriptName.split("\\.");
            String scripNamePre = splitNameArr[0];
            Script script = groovyShell.parse(scriptFile);
            scriptMap.put(scripNamePre, script);
        }
    }

    /**
     * 获取脚本
     * @param scriptName 脚本名称
     * @return
     */
    public static Script getScript(String scriptName) {
        Script script = scriptMap.get(scriptName);
        return script;
    }

}
